﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using IEMSOFT.EasyHotel.Admin.Models;
using IEMSOFT.EasyHotel.DAL;
using IEMSOFT.EasyHotel.DAL.Models;
using IEMSOFT.EasyHotel.Common;
using IEMSOFT.Foundation;
namespace IEMSOFT.EasyHotel.Admin.Lib
{
    public class BillBLL
    {
        public static BillModel Create(BillCreateModel billCreateInfo)
        {
            var bill = AutoMapper.Mapper.Map<BillModel>(billCreateInfo);
            bill.BillStatus = BillStatusType.Pending.ToInt();
            using (var db = new EasyHotelDB())
            {
                var billDAL = new BillDAL(db);
                var billMap = AutoMapper.Mapper.Map<Bill>(bill);
                var result = billDAL.Create(billMap);
                bill.BillId = result.BillId;
            }
            return bill;
        }

        public static void Update(BillBasicModel billUpdateInfo)
        {
            using (var db = new EasyHotelDB())
            {
                var billDAL = new BillDAL(db);
                var bill = billDAL.GetOneBill(billUpdateInfo.BillId);
                bill.BillNo = billUpdateInfo.BillNo;
                bill.CheckinDate = billUpdateInfo.CheckinDate.ToDateTime();
                bill.CustomerIDNo = billUpdateInfo.CustomerIDNo;
                bill.CustomerName = billUpdateInfo.CustomerName;
                bill.PayTypeId = billUpdateInfo.PayTypeId;
                bill.RoomId = billUpdateInfo.RoomId;
                bill.SinglePrice = billUpdateInfo.SinglePrice;
                bill.TravelAgencyId = billUpdateInfo.TravelAgencyId;
                bill.UpdatedByUserId = billUpdateInfo.UpdatedByUserId;
                bill.Deposit = billUpdateInfo.Deposit;
                bill.Modified = DateTime.Now;
                bill.ConsumeFee = billUpdateInfo.ConsumeFee;
                bill.ConsumeItem = billUpdateInfo.ConsumeItem;
                bill.Comments = billUpdateInfo.Comments;
                bill.MinFeeForHourRoom = billUpdateInfo.MinFeeForHourRoom;
                bill.PricePerHour = billUpdateInfo.PricePerHour;
                bill.IsHourRoom = billUpdateInfo.IsHourRoom;
                billDAL.Save(bill);
            }
        }

        public static void CancelCheckin(int roomId, int updatedUserId)
        {
            using (var db = new EasyHotelDB())
            {
                var billDAL = new BillDAL(db);
                var pendingBill = billDAL.GetOnePendingBill(DateTime.Now, roomId);
                billDAL.Cancel(pendingBill.BillId, updatedUserId);
            }
        }
        public static BillModel GetOnePendingBill(DateTime checkinDate, int roomId)
        {
            using (var db = new EasyHotelDB())
            {
                var billDAL = new BillDAL(db);
                var pendingBill = billDAL.GetOnePendingBill(DateTime.Now, roomId);
                var ret = AutoMapper.Mapper.Map<BillModel>(pendingBill);
                return ret;
            }

        }

        /// <summary>
        /// 订单预结算
        /// </summary>
        /// <param name="roomId"></param>
        /// <returns></returns>
        public static BillModel PreSettle(int roomId, DateTime checkOutDate, int updateByUserId = 0)
        {
            var ret = GetOnePendingBill(DateTime.Now, roomId);
            if (ret != null)
            {
                ret.BillStatus = BillStatusType.Finished.ToInt();
                ret.CheckoutDate = checkOutDate.ToLongDateStr();
                ret.Modified = checkOutDate.ToLongDateStr();
                if (ret.IsHourRoom.ToBool())
                {
                    ret.StayTotalDays = 0;
                    var minHours = Utility.GetAppSetting<int>(3, "MinHoursForHourRoom"); 
                    ret.StayTotalHours = CaculateStayHours(ret.CheckinDate.ToDateTime(), checkOutDate);
                    if (ret.StayTotalHours <= minHours)
                        ret.RoomTotalFee = ret.MinFeeForHourRoom;
                    else
                        ret.RoomTotalFee = (ret.MinFeeForHourRoom + (ret.StayTotalHours-minHours) * ret.PricePerHour);
                }
                else
                {
                    ret.StayTotalHours = 0;
                    ret.MinFeeForHourRoom = 0;
                    ret.PricePerHour = 0;
                    ret.StayTotalDays = CaculateStayDays(ret.CheckinDate.ToDateTime(), ret.CheckoutDate.ToDateTime());
                    ret.RoomTotalFee = Decimal.Round(ret.SinglePrice * ret.StayTotalDays, 2);
                }
                ret.UpdatedByUserId = updateByUserId;
            }
            return ret;
        }

        public static int CaculateStayDays(DateTime checkinDate, DateTime checkoutDate)
        {
            var days = 0;
            var billSettleTimeStr = Utility.GetAppSetting<string>("14:00:00", "BillSettleTime");
            var startDateStr = checkinDate.ToShortDateStr();
            var endDateStr = checkoutDate.ToShortDateStr();
            var startDate = startDateStr.ToDateTime();
            var endDate = endDateStr.ToDateTime();
            var billSettleTime = string.Format("{0} {1}", endDateStr, billSettleTimeStr).ToDateTime();
            if (startDate == endDate)//当天退房
            {
                days = 1;
            }
            else
            {
                days = (endDate - startDate).TotalDays.ToInt();
                if (checkoutDate > billSettleTime)//超过结算时间，多加1天
                {
                    days = days + 1;
                }

            }
            return days;
        }


        public static int CaculateStayHours(DateTime checkinDate, DateTime checkoutDate)
        {
            var hour = Math.Ceiling((checkoutDate - checkinDate).TotalHours).ToInt();
            return hour;
        }

        public static void Settle(long billId,
                                  DateTime checkoutDate,
                                  int stayTotalDays,
                                  decimal roomTotalFee,
                                  decimal consumeFee,
                                  string consumeItem,
                                  string comments,
                                  int stayTotalHours
                                   )
        {
            using (var db = new EasyHotelDB())
            {
                var billDAL = new BillDAL(db);
                billDAL.Settle(billId, checkoutDate, stayTotalDays, roomTotalFee, consumeFee, consumeItem, comments, stayTotalHours);
            }
        }

        public static List<BillFullModel> SearchFinishedBills(string fromDate,
                                                     string endDate,
                                                     int? roomTypeId,
                                                     int? travelAgencyId,
                                                     int? payTypeId,
                                                     int? subHotelId,
                                                     int? createdByUserId,
                                                     int groupHotelId)
        {
            using (var db = new EasyHotelDB())
            {
                var billDAL = new BillDAL(db);
                var bills = billDAL.SearchFinishedBills(fromDate,
                                                        endDate,
                                                        roomTypeId,
                                                        travelAgencyId,
                                                        payTypeId,
                                                        subHotelId,
                                                        createdByUserId,
                                                        groupHotelId);
                var ret = AutoMapper.Mapper.Map<List<BillFullModel>>(bills);
                return ret;
            }
        }

        public static List<MonthReportMode> SearchMonthReport(string fromDate,
                                                  string endDate,
                                                  int? roomTypeId,
                                                  int? travelAgencyId,
                                                  int? payTypeId,
                                                  int? subHotelId,
                                                  int? createdByUserId,
                                                  int groupHotelId)
        {

            var bills = SearchFinishedBills(fromDate,
                                            endDate,
                                            roomTypeId,
                                            travelAgencyId,
                                            payTypeId,
                                            subHotelId,
                                            createdByUserId,
                                            groupHotelId);
            foreach (var item in bills)
            {
                item.CheckoutDate = item.CheckoutDate.ToDateTime().ToString("yyyyMM");
            }
            var data = (from item in bills
                        group item by item.CheckoutDate into g
                        select new MonthReportMode
                        {
                            Month = g.Key,
                            BillsRoomTotalFee = g.Sum(bill => bill.RoomTotalFee),
                            BillsConsumeTotalFee = g.Sum(bill => bill.ConsumeFee),
                            BillsTotalFee = g.Sum(bill => bill.RoomTotalFee) + g.Sum(bill => bill.ConsumeFee),
                            BillsCount = g.Count()
                        }).OrderBy(t => t.Month);
            return data.ToList();
        }
    }
}